{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- ancestor\t\t\t\t选取当前节点的所有先辈（父、祖父等）。\n",
    "- ancestor-or-self\t\t选取当前节点的所有先辈（父、祖父等）以及当前节点本身。\n",
    "- attribute\t\t\t\t选取当前节点的所有属性。\n",
    "- child\t\t\t\t\t选取当前节点的所有子元素。\n",
    "- descendant\t\t\t选取当前节点的所有后代元素（子、孙等）。\n",
    "- descendant-or-self\t选取当前节点的所有后代元素（子、孙等）以及当前节点本身。\n",
    "- following\t\t\t\t选取文档中当前节点的结束标签之后的所有节点。\n",
    "- namespace\t\t\t\t选取当前节点的所有命名空间节点。\n",
    "- parent\t\t\t\t选取当前节点的父节点。\n",
    "- preceding\t\t\t\t选取文档中当前节点的开始标签之前的所有节点。\n",
    "- preceding-sibling\t\t选取当前节点之前的所有同级节点。\n",
    "- self\t\t\t\t\t选取当前节点。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "from lxml import etree\n",
    "html_str = \"\"\"\n",
    "<body id=\"body\" class=\"bodyname\">\n",
    "<div class=\"ui container\">\n",
    "        <span-prev>span prev text1</span-prev>\n",
    "        <span-prev>span prev text2</span-prev>\n",
    "        <table id=\"table\" class=\"ui striped  table\" style=\"background-color:color;\" sdkhfs=\"11223344\">\n",
    "            <tr class=\"one\">\n",
    "                <th>姓名</th>\n",
    "                <th>性别</th>\n",
    "                <th>邮箱</th>\n",
    "                <th>电话</th>\n",
    "            </tr>\n",
    "            <tr class=\"one two\">\n",
    "                <td><a href=\"zhangwei\">张伟</a></td>\n",
    "                <td>男</td>\n",
    "                <td>zhangwei@haoren.com</td>\n",
    "                <td>12138-111</td>\n",
    "            </tr>\n",
    "            <tr class=\"one three\">\n",
    "                <td><a href=\"yifei\">一菲</a></td>\n",
    "                <td>女</td>\n",
    "                <td>yifei@haoren.com</td>\n",
    "                <td>12138-112</td>\n",
    "            </tr>\n",
    "            <tr class=\"four\">\n",
    "                <td><a href=\"xiaoxian\">小贤</a></td>\n",
    "                <td>男</td>\n",
    "                <td>xiaoxian@haoren.com</td>\n",
    "                <td>12138-113</td>\n",
    "            </tr>\n",
    "            <tr class=\"five\">\n",
    "                <td><a href=\"meijia\">美嘉</a></td>\n",
    "                <td>女</td>\n",
    "                <td>meijia@haoren.com</td>\n",
    "                <td>12138-114</td>\n",
    "            </tr>\n",
    "            <tr class=\"five six\">\n",
    "                <td><a href=\"xiaobu\">小布</a></td>\n",
    "                <td>男</td>\n",
    "                <td>xiaobu@hundan.com</td>\n",
    "                <td>12138-115</td>\n",
    "            </tr>\n",
    "            <a class=\"linkurl\">link</a>\n",
    "        </table>\n",
    "        <span-next>span next text3</span-next>\n",
    "        <span-next>span next text4</span-next>\n",
    "</div>\n",
    "</body>\n",
    "\"\"\"\n",
    "\n",
    "html = etree.HTML(html_str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<Element table at 0x7fd5975792d0>]\n"
     ]
    }
   ],
   "source": [
    "print(html.xpath('.//table[@id=\"table\"]'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<Element html at 0x7fd59751c460>, <Element body at 0x7fd597204870>, <Element div at 0x7fd59763c820>]\n",
      "[<Element body at 0x7fd597204870>]\n",
      "----------------------------------------\n",
      "[<Element html at 0x7fd59751c460>, <Element body at 0x7fd597204870>, <Element div at 0x7fd59763cc80>, <Element table at 0x7fd59763cc30>]\n",
      "----------------------------------------\n",
      "[<Element tr at 0x7fd597512af0>, <Element tr at 0x7fd597204870>, <Element tr at 0x7fd59763cc80>, <Element tr at 0x7fd59763cc30>, <Element tr at 0x7fd59763ccd0>, <Element tr at 0x7fd59763cd20>]\n",
      "[<Element tr at 0x7fd597512af0>, <Element tr at 0x7fd597204870>, <Element tr at 0x7fd59763cc80>, <Element tr at 0x7fd59763cc30>, <Element tr at 0x7fd59763ccd0>, <Element tr at 0x7fd59763cd20>]\n"
     ]
    }
   ],
   "source": [
    "# ancestor 选取当前节点的所有先辈（父、祖父等）。\n",
    "print(html.xpath('.//table/ancestor::*'))\n",
    "print(html.xpath('.//table/ancestor::body'))\n",
    "print('----' * 10)\n",
    "print(html.xpath('.//table/ancestor-or-self::*'))\n",
    "print('----' * 10)\n",
    "print(html.xpath('.//table/*'))\n",
    "print(html.xpath('.//table/tr'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<Element table at 0x7fd597642690>]\n",
      "[]\n",
      "['table', 'ui striped  table', 'background-color:color;', '11223344']\n",
      "['background-color:color;']\n"
     ]
    }
   ],
   "source": [
    "# attribute 选取当前节点的所有属性。\n",
    "print(html.xpath('.//table'))\n",
    "print(html.xpath('.//table/attribute'))\n",
    "print(html.xpath('.//table/attribute::*'))\n",
    "print(html.xpath('.//table/attribute::style'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<Element tr at 0x7fd598d9b820>, <Element tr at 0x7fd598cb00f0>, <Element tr at 0x7fd598cb0820>, <Element tr at 0x7fd598cb0910>, <Element tr at 0x7fd598cb0a50>, <Element tr at 0x7fd598cb0280>, <Element a at 0x7fd598cb0780>]\n",
      "[<Element tr at 0x7fd598d9b820>, <Element tr at 0x7fd598cb00f0>, <Element tr at 0x7fd598cb0820>, <Element tr at 0x7fd598cb0910>, <Element tr at 0x7fd598cb0a50>, <Element tr at 0x7fd598cb0280>, <Element a at 0x7fd598cb0780>]\n",
      "----------------------------------------\n",
      "[<Element tr at 0x7fd598d9b820>, <Element th at 0x7fd598cb00f0>, <Element th at 0x7fd598cb0820>, <Element th at 0x7fd598cb0910>, <Element th at 0x7fd598cb0a50>, <Element tr at 0x7fd598cb0280>, <Element td at 0x7fd598cb0780>, <Element a at 0x7fd598daaa50>, <Element td at 0x7fd598daa550>, <Element td at 0x7fd598fafaf0>, <Element td at 0x7fd598faf820>, <Element tr at 0x7fd598fafdc0>, <Element td at 0x7fd598faf7d0>, <Element a at 0x7fd598faf640>, <Element td at 0x7fd598faf2d0>, <Element td at 0x7fd598faf730>, <Element td at 0x7fd598faf690>, <Element tr at 0x7fd598faf410>, <Element td at 0x7fd598faf140>, <Element a at 0x7fd598faf5a0>, <Element td at 0x7fd598fafa50>, <Element td at 0x7fd598f2b780>, <Element td at 0x7fd598f2b550>, <Element tr at 0x7fd598f2bf00>, <Element td at 0x7fd598f2bb40>, <Element a at 0x7fd598f2b820>, <Element td at 0x7fd598f2b1e0>, <Element td at 0x7fd598f2b9b0>, <Element td at 0x7fd598f2b4b0>, <Element tr at 0x7fd598faddc0>, <Element td at 0x7fd598fad4b0>, <Element a at 0x7fd598fad780>, <Element td at 0x7fd598fadaa0>, <Element td at 0x7fd598fadc80>, <Element td at 0x7fd598fade60>, <Element a at 0x7fd598fad0f0>]\n",
      "36\n",
      "36\n",
      "----------------------------------------\n",
      "[<Element table at 0x7fd598d9b820>, <Element tr at 0x7fd598cb00f0>, <Element th at 0x7fd598cb0820>, <Element th at 0x7fd598cb0910>, <Element th at 0x7fd598cb0a50>, <Element th at 0x7fd598cb0280>, <Element tr at 0x7fd598cb0780>, <Element td at 0x7fd598daaa50>, <Element a at 0x7fd598daa550>, <Element td at 0x7fd598fafaf0>, <Element td at 0x7fd598faf820>, <Element td at 0x7fd598fafdc0>, <Element tr at 0x7fd598faf7d0>, <Element td at 0x7fd598faf640>, <Element a at 0x7fd598faf2d0>, <Element td at 0x7fd598faf730>, <Element td at 0x7fd598faf690>, <Element td at 0x7fd598faf410>, <Element tr at 0x7fd598faf140>, <Element td at 0x7fd598faf5a0>, <Element a at 0x7fd598fafa50>, <Element td at 0x7fd598f2b780>, <Element td at 0x7fd598f2b550>, <Element td at 0x7fd598f2bf00>, <Element tr at 0x7fd598f2bb40>, <Element td at 0x7fd598f2b820>, <Element a at 0x7fd598f2b1e0>, <Element td at 0x7fd598f2b9b0>, <Element td at 0x7fd598f2b4b0>, <Element td at 0x7fd598faddc0>, <Element tr at 0x7fd598fad4b0>, <Element td at 0x7fd598fad780>, <Element a at 0x7fd598fadaa0>, <Element td at 0x7fd598fadc80>, <Element td at 0x7fd598fade60>, <Element td at 0x7fd598fad0f0>, <Element a at 0x7fd598fadbe0>]\n"
     ]
    }
   ],
   "source": [
    "# child 选取当前节点的所有子元素。\n",
    "# descendant 选取当前节点的所有后代元素（子、孙等）。\n",
    "# descendant-or-self 选取当前节点的所有后代元素（子、孙等）以及当前节点本身。\n",
    "\n",
    "print(html.xpath('.//table/child::*'))\n",
    "print(html.xpath('.//table/*'))\n",
    "print('----' * 10)\n",
    "\n",
    "# 子孙级\n",
    "print(html.xpath('.//table/descendant::*'))\n",
    "print(len(html.xpath('.//table/descendant::*')))\n",
    "print(len(html.xpath('.//table//*')))\n",
    "\n",
    "print('----' * 10)\n",
    "# 子孙级 并且包含自身\n",
    "print(html.xpath('.//table/descendant-or-self::*'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['span next text3', 'span next text4']\n",
      "['span prev text1', 'span prev text2']\n"
     ]
    }
   ],
   "source": [
    "# following 选取文档中当前节点的结束标签之后的所有节点。\n",
    "print(html.xpath('.//table/following::*/text()'))\n",
    "\n",
    "# preceding 选取文档中当前节点的开始标签之前的所有节点。\n",
    "print(html.xpath('.//table/preceding::*/text()'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['span prev text1', 'span prev text2']\n",
      "['span next text3', 'span next text4']\n"
     ]
    }
   ],
   "source": [
    "# preceding-sibling 选取当前节点之前的所有同级节点。\n",
    "print(html.xpath('.//table/preceding-sibling::*/text()'))\n",
    "\n",
    "# following-sibling 选取当前节点之后的所有同级节点。\n",
    "print(html.xpath('.//table/following-sibling::*/text()'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<Element table at 0x7fd598a72fa0>]\n",
      "[<Element table at 0x7fd598a72fa0>]\n",
      "----------------------------------------\n",
      "[<Element div at 0x7fd598a72fa0>]\n",
      "[<Element div at 0x7fd598a72fa0>]\n",
      "[('xml', 'http://www.w3.org/XML/1998/namespace')]\n"
     ]
    }
   ],
   "source": [
    "# namespace 选取当前节点的所有命名空间节点。\n",
    "# parent 选取当前节点的父节点。\n",
    "# self 选取当前节点。\n",
    "\n",
    "print(html.xpath('.//table/self::*'))\n",
    "print(html.xpath('.//table/.'))\n",
    "print('----------------------------------------')\n",
    "print(html.xpath('.//table/parent::*'))\n",
    "print(html.xpath('.//table/..'))\n",
    "print(html.xpath('.//table/namespace::*'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
